using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using JGSY.CMS.LowCode.Platform.Application.DTOs;
using JGSY.CMS.LowCode.Platform.Application.Interfaces;
using JGSY.CMS.LowCode.Platform.Domain.Entities;
using JGSY.CMS.LowCode.Platform.Domain.Interfaces;

namespace JGSY.CMS.LowCode.Platform.Application.Services
{
    /// <summary>
    /// 表单应用服务实现
    /// 提供表单的完整生命周期管理，包括表单设计、发布、提交处理、数据统计等核心功能
    /// 支持动态表单字段配置、提交验证、数据导出、批量操作等业务场景
    /// 集成表单模板、自动化规则、通知机制等高级特性
    /// </summary>
    public class FormAppService : IFormAppService
    {
        /// <summary>
        /// 表单数据仓储
        /// </summary>
        private readonly IFormRepository _formRepository;
        
        /// <summary>
        /// 表单提交数据仓储
        /// </summary>
        private readonly IFormSubmissionRepository _submissionRepository;
        
        /// <summary>
        /// 日志记录器
        /// </summary>
        private readonly ILogger<FormAppService> _logger;

        /// <summary>
        /// 初始化表单应用服务实例
        /// </summary>
        /// <param name="formRepository">表单数据仓储</param>
        /// <param name="submissionRepository">表单提交数据仓储</param>
        /// <param name="logger">日志记录器</param>
        /// <exception cref="ArgumentNullException">当依赖项为null时抛出</exception>
        public FormAppService(
            IFormRepository formRepository,
            IFormSubmissionRepository submissionRepository,
            ILogger<FormAppService> logger)
        {
            _formRepository = formRepository ?? throw new ArgumentNullException(nameof(formRepository));
            _submissionRepository = submissionRepository ?? throw new ArgumentNullException(nameof(submissionRepository));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        }

        /// <summary>
        /// 批量删除表单
        /// 根据表单ID列表执行批量删除操作，支持事务处理确保数据一致性
        /// </summary>
        /// <param name="ids">要删除的表单ID集合</param>
        /// <returns>实际删除的表单数量</returns>
        /// <exception cref="ArgumentNullException">当ids为null时抛出</exception>
        /// <exception cref="InvalidOperationException">当删除操作失败时抛出</exception>
        public async Task<int> BatchDeleteAsync(IEnumerable<long> ids)
        {
            try
            {
                var count = await _formRepository.BatchDeleteAsync(ids);
                _logger.LogInformation("批量删除表单完成，数量: {Count}", count);
                return count;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "批量删除表单失败");
                throw;
            }
        }

        /// <summary>
        /// 清理过期的表单提交数据
        /// 自动清理指定天数之前的表单提交记录，优化数据库性能和存储空间
        /// 采用软删除策略，将过期提交标记为已忽略状态而非物理删除
        /// </summary>
        /// <param name="daysToKeep">保留天数，默认365天</param>
        /// <returns>清理的提交记录数量</returns>
        /// <exception cref="ArgumentException">当daysToKeep小于等于0时抛出</exception>
        /// <exception cref="InvalidOperationException">当清理操作失败时抛出</exception>
        public async Task<int> CleanupExpiredSubmissionsAsync(int daysToKeep = 365)
        {
            // 将过期提交标记为已忽略（2）
            var cutoff = DateTime.UtcNow.AddDays(-Math.Abs(daysToKeep));
            var expired = await _submissionRepository.FindAsync(fs => fs.SubmitTime <= cutoff);
            var ids = expired.Select(i => i.Id).ToList();
            if (ids.Count == 0) return 0;
            var ok = await _submissionRepository.BatchUpdateStatusAsync(ids, "2");
            return ok ? ids.Count : 0;
        }

        public async Task<FormDto> CreateAsync(FormDto formDto)
        {
            var entity = new Form
            {
                Name = formDto.Name,
                Description = formDto.Description,
                Fields = formDto.Fields,
                Settings = formDto.Settings,
                Rules = formDto.ValidationRules,
                SuccessMessage = formDto.SuccessMessage,
                SortOrder = formDto.SortOrder,
                Status = formDto.Status,
                CreatedBy = formDto.CreatedBy,
                UpdatedBy = formDto.UpdatedBy,
                CreatedAt = DateTime.UtcNow,
                UpdatedAt = DateTime.UtcNow
            };

            await _formRepository.AddAsync(entity);
            _logger.LogInformation("创建表单成功: {Name}", entity.Name);
            return MapToDto(entity);
        }

        public async Task<bool> DeleteAsync(long id)
        {
            await _formRepository.DeleteAsync(id);
            return true;
        }

        public async Task<FormDto> DuplicateAsync(long id, string newName, string newIdentifier)
        {
            var form = await _formRepository.GetByIdAsync(id);
            if (form == null) throw new ArgumentException("表单不存在");
            var copy = new Form
            {
                Name = newIdentifier, // 使用 Identifier 作为 Name 的存储
                Description = form.Description,
                Fields = form.Fields,
                Settings = form.Settings,
                Rules = form.Rules,
                SuccessMessage = form.SuccessMessage,
                SortOrder = form.SortOrder,
                Status = form.Status,
                CreatedBy = form.CreatedBy,
                UpdatedBy = form.UpdatedBy,
                CreatedAt = DateTime.UtcNow,
                UpdatedAt = DateTime.UtcNow
            };
            await _formRepository.AddAsync(copy);
            var dto = MapToDto(copy);
            dto.Name = newName;
            dto.Identifier = newIdentifier;
            return dto;
        }

        public async Task<string?> ExportFormSubmissionsAsync(long formId, string format = "excel")
        {
            var fileName = $"form_{formId}_submissions_{DateTime.UtcNow:yyyyMMddHHmmss}.csv";
            var temp = System.IO.Path.Combine(System.IO.Path.GetTempPath(), fileName);
            var subs = await _submissionRepository.GetByFormIdAsync(formId);
            try
            {
                var lines = subs.Select(s => $"{s.Id},{s.SubmitTime:o},{(int)s.Status},\"{(s.Data ?? string.Empty).Replace("\"", "\"\"")}\"");
                await System.IO.File.WriteAllLinesAsync(temp, lines);
                return temp;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "导出表单提交失败: {FormId}", formId);
                return null;
            }
        }

        public async Task<IEnumerable<FormDto>> GetActiveFormsAsync()
        {
            var items = await _formRepository.GetActiveFormsAsync();
            return items.Select(MapToDto);
        }

        public async Task<IEnumerable<FormDto>> GetAllAsync()
        {
            var items = await _formRepository.GetAllAsync();
            return items.Select(MapToDto);
        }

        public async Task<FormDto?> GetByIdAsync(long id)
        {
            var entity = await _formRepository.GetByIdAsync(id);
            return entity == null ? null : MapToDto(entity);
        }

        public async Task<FormDto?> GetByIdentifierAsync(string identifier)
        {
            var entity = await _formRepository.GetByIdentifierAsync(identifier);
            return entity == null ? null : MapToDto(entity);
        }

        public async Task<object> GetFormStatisticsAsync(long formId)
        {
            return await _formRepository.GetFormStatisticsAsync(formId);
        }

        public async Task<(IEnumerable<object> Items, int TotalCount)> GetFormSubmissionsAsync(long formId, int pageIndex = 1, int pageSize = 20)
        {
            var zero = Math.Max(0, pageIndex - 1);
            System.Linq.Expressions.Expression<Func<FormSubmission, bool>> predicate = s => s.FormId == formId && s.Status != 0;
            var (items, total) = await _submissionRepository.GetPagedAsync(zero, pageSize, predicate);
            return (items.Select(s => new { s.Id, s.SubmitTime, s.Status, s.Data }), total);
        }

        public async Task<(IEnumerable<FormDto> Items, int TotalCount)> GetPagedAsync(int pageIndex, int pageSize, string? keyword = null, byte? status = null)
        {
            var (items, total) = await _formRepository.GetPagedAsync(pageIndex, pageSize, keyword, status);
            return (items.Select(MapToDto), total);
        }

        public Task<bool> IdentifierExistsAsync(string identifier, long? excludeId = null)
        {
            return _formRepository.IdentifierExistsAsync(identifier, excludeId);
        }

        public async Task<string?> PreviewFormAsync(long id)
        {
            var form = await _formRepository.GetByIdAsync(id);
            if (form == null) return null;
            // 简单拼装预览 HTML
            return $"<h1>{System.Net.WebUtility.HtmlEncode(form.Name)}</h1><div>{System.Net.WebUtility.HtmlEncode(form.Description)}</div>";
        }

        public async Task<object> SubmitFormDataAsync(long formId, Dictionary<string, object> data, string? userAgent = null, string? ipAddress = null)
        {
            var form = await _formRepository.GetByIdAsync(formId);
            if (form == null) throw new ArgumentException("表单不存在");

            var submission = new FormSubmission
            {
                FormId = formId,
                Data = System.Text.Json.JsonSerializer.Serialize(data),
                UserAgent = userAgent,
                SubmitterIp = ipAddress,
                SubmitTime = DateTime.UtcNow,
                Status = 1
            };

            await _submissionRepository.AddAsync(submission);
            await _formRepository.IncrementSubmissionCountAsync(formId);

            return new { submission.Id, submission.SubmitTime };
        }

        public async Task<FormDto> UpdateAsync(FormDto formDto)
        {
            var entity = await _formRepository.GetByIdAsync(formDto.Id) ?? throw new ArgumentException("表单不存在");
            entity.Name = string.IsNullOrWhiteSpace(formDto.Identifier) ? formDto.Name : formDto.Identifier;
            entity.Description = formDto.Description;
            entity.Fields = formDto.Fields;
            entity.Settings = formDto.Settings;
            entity.Rules = formDto.ValidationRules;
            entity.SuccessMessage = formDto.SuccessMessage;
            entity.SortOrder = formDto.SortOrder;
            entity.Status = formDto.Status;
            entity.UpdatedBy = formDto.UpdatedBy;
            entity.UpdatedAt = DateTime.UtcNow;
            await _formRepository.UpdateAsync(entity);
            return MapToDto(entity);
        }

        public async Task<bool> UpdateStatusAsync(long id, byte status)
        {
            var form = await _formRepository.GetByIdAsync(id);
            if (form == null) return false;
            form.Status = status;
            form.UpdatedAt = DateTime.UtcNow;
            await _formRepository.UpdateAsync(form);
            return true;
        }

        public Task<(bool IsValid, List<string> Errors)> ValidateFormConfigurationAsync(FormDto formDto)
        {
            var errors = new List<string>();
            if (string.IsNullOrWhiteSpace(formDto.Name)) errors.Add("表单名称不能为空");
            if (string.IsNullOrWhiteSpace(formDto.Identifier)) errors.Add("表单标识符不能为空");
            // 可加入更多 JSON 结构校验
            return Task.FromResult<(bool, List<string>)>((errors.Count == 0, errors));
        }

        private static FormDto MapToDto(Form form)
        {
            return new FormDto
            {
                Id = form.Id,
                Name = form.Name,
                Identifier = form.Name, // 当前模型未单独存储 Identifier，使用 Name 代表
                Description = form.Description,
                Fields = form.Fields,
                Settings = form.Settings,
                ValidationRules = form.Rules,
                SuccessMessage = form.SuccessMessage,
                SubmissionCount = form.SubmissionCount,
                SortOrder = form.SortOrder,
                Status = form.Status,
                CreatedBy = form.CreatedBy,
                UpdatedBy = form.UpdatedBy,
                CreatedAt = form.CreatedAt,
                UpdatedAt = form.UpdatedAt,
                IsActive = form.Status == 1
            };
        }
    }
}
